package com.easygoods.service;

import com.bestvike.linq.Linq;
import com.bestvike.stone.core.lang.BeanUtils;
import com.bestvike.stone.core.lang.Convert;
import com.bestvike.stone.core.lang.RandomUtils;
import com.bestvike.stone.core.lang.StringUtils;
import com.bestvike.stone.core.time.DateUtils;
import com.bestvike.stone.core.time.TimeSpan;
import com.bestvike.stone.spring.exception.BusinessException;
import com.bestvike.stone.spring.exception.ErrorCode;
import com.bestvike.stone.spring.service.BaseService;
import com.easygoods.dao.ExpressInfoDao;
import com.easygoods.dao.OrderInfoDao;
import com.easygoods.dao.OrderTraceDao;
import com.easygoods.entity.ExpressInfo;
import com.easygoods.entity.OrderInfo;
import com.easygoods.entity.OrderTrace;
import com.easygoods.enums.OrderState;
import com.easygoods.enums.OrderTraceState;
import com.easygoods.external.kdniao.KdNiaoApi;
import com.easygoods.external.kdniao.bean.KdNiaoOrderTraceRequest;
import com.easygoods.external.kdniao.bean.KdNiaoOrderTraceResponse;
import com.easygoods.response.OrderTraceResponse;
import com.easygoods.response.OrderTraceResponseStation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;

/**
 * Created by 许崇雷 on 2019-01-14.
 */
@Service
public class OrderTraceService extends BaseService {
    private static final TimeSpan SYNC_SPAN = new TimeSpan(0, 10, 0);//追踪间隔
    private static final Integer OVERDUE_SIGN_DAYS = 7;
    @Autowired
    private KdNiaoApi kdNiaoApi;
    @Autowired
    private OrderInfoDao orderInfoDao;
    @Autowired
    private ExpressInfoDao expressInfoDao;
    @Autowired
    private OrderTraceDao orderTraceDao;
    @Autowired
    private OrderService orderService;

    //获取物流追踪
    @Transactional
    public OrderTraceResponse getOrderTraces(String orderId) {
        final OrderInfo orderInfo = this.orderInfoDao.selectByPrimaryKey(orderId);
        if (orderInfo == null)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "无效订单号");
        OrderState orderState = Convert.toType(orderInfo.getState(), OrderState.class);
        if (orderState == null) {
            this.log.error("订单状态为 null,id:" + orderInfo.getId());
            throw new BusinessException(ErrorCode.ERROR_SERVER, "订单状态错误");
        }

        //未填写发货信息
        String expressId = orderInfo.getExpressId();//快递公司代码
        String expressOrderId = orderInfo.getExpressOrderId();//运单号
        if (StringUtils.isEmpty(expressId) || StringUtils.isEmpty(expressOrderId)) {
            OrderTraceResponse response = new OrderTraceResponse();
            response.setExpressOrderState(OrderTraceState.ToSend.name());
            return response;
        }

        //读取快递公司信息
        ExpressInfo expressInfo = this.expressInfoDao.selectByPrimaryKey(expressId);
        if (expressInfo == null)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "快递公司被删除,联系平台");
        String expressName = expressInfo.getExpressName();

        //未超时,读取数据库
        Date expressTraceTime = orderInfo.getExpressTraceTime();
        if (expressTraceTime != null && new TimeSpan(DateUtils.now(), expressTraceTime).getTotalMilliseconds() <= SYNC_SPAN.getTotalMilliseconds()) {
            Example example = new Example(OrderTrace.class);
            example.createCriteria().andEqualTo(OrderTrace.ORDER_ID, orderId);
            example.orderBy(OrderTrace.ACCEPT_TIME).desc();
            List<OrderTrace> orderTraces = this.orderTraceDao.selectByExample(example);
            OrderTraceResponse response = new OrderTraceResponse();
            response.setExpressId(orderInfo.getExpressId());
            response.setExpressName(expressName);
            response.setExpressOrderId(expressOrderId);
            response.setExpressOrderState(orderInfo.getExpressOrderState());
            response.setTraces(BeanUtils.toList(orderTraces, OrderTraceResponseStation.class));
            return response;
        }

        //查询 api
        KdNiaoOrderTraceRequest kdNiaoOrderTraceRequest = new KdNiaoOrderTraceRequest();
        kdNiaoOrderTraceRequest.setShipperCode(expressId);
        kdNiaoOrderTraceRequest.setLogisticCode(expressOrderId);
        KdNiaoOrderTraceResponse orderTraces = this.kdNiaoApi.getOrderTraces(kdNiaoOrderTraceRequest);
        //更新订单表
        OrderTraceState orderTraceState = OrderTraceState.fromCode(Convert.defaultInteger(orderTraces.getState()));
        if (orderTraceState == null)
            orderTraceState = OrderTraceState.Exception;
        OrderInfo orderInfoUpdate = new OrderInfo();
        orderInfoUpdate.setId(orderId);
        orderInfoUpdate.setExpressOrderState(orderTraceState.name());
        boolean isExpiredSignTime = DateUtils.add(orderInfo.getSendTime(), OVERDUE_SIGN_DAYS, 0, 0, 0, 0).compareTo(DateUtils.now()) < 0;
        if (orderState == OrderState.UnderWay && (orderTraceState == OrderTraceState.Signed || isExpiredSignTime))//订单为已发货,并且物流为签收则完成订单
            this.orderService.signOrder(orderId);
        orderInfoUpdate.setExpressTraceTime(DateUtils.now());
        this.orderInfoDao.updateByPrimaryKeySelective(orderInfoUpdate);
        //删除旧的追踪
        Example example = new Example(OrderTrace.class);
        example.createCriteria().andEqualTo(OrderTrace.ORDER_ID, orderId);
        this.orderTraceDao.deleteByExample(example);
        if (orderTraces.getTraces() == null) {
            OrderTraceResponse response = new OrderTraceResponse();
            response.setExpressId(orderInfo.getExpressId());
            response.setExpressName(expressName);
            response.setExpressOrderId(expressOrderId);
            response.setExpressOrderState(orderInfo.getExpressOrderState());
            return response;
        }
        //插入新的追踪
        List<OrderTrace> orderTracesList = Linq.asEnumerable(orderTraces.getTraces())
                .select(a -> {
                    OrderTrace orderTrace = new OrderTrace();
                    orderTrace.setId(RandomUtils.randomUUID());
                    orderTrace.setOrderId(orderId);
                    orderTrace.setAcceptTime(a.getAcceptTime());
                    orderTrace.setAcceptStation(a.getAcceptStation());
                    orderTrace.setRemark(a.getRemark());
                    orderTrace.beforeInsert();
                    return orderTrace;
                })
                .orderByDescending(OrderTrace::getAcceptTime)
                .toList();
        for (OrderTrace orderTrace : orderTracesList) {
            this.orderTraceDao.insert(orderTrace);
        }

        //返回
        OrderTraceResponse response = new OrderTraceResponse();
        response.setExpressId(orderInfo.getExpressId());
        response.setExpressName(expressName);
        response.setExpressOrderId(expressOrderId);
        response.setExpressOrderState(orderInfo.getExpressOrderState());
        response.setTraces(BeanUtils.toList(orderTracesList, OrderTraceResponseStation.class));
        return response;
    }
}
